﻿using FrameworkCore.Migrations.Data;
using FrameworkCore.Models;
using Microsoft.EntityFrameworkCore.Query;
using System.Linq.Expressions;
namespace FrameworkCore.Repositories;

#nullable disable

/// <summary>
/// 表示一个实体仓储接口
/// </summary>
/// <typeparam name="TEntity">实体类型</typeparam>
public partial interface IRepository<TEntity> where TEntity : BaseEntity
{
    #region 增删改查

    /// <summary>
    /// 获取实体条目
    /// </summary>
    /// <param name="predicate">用于测试每个元素条件的函数</param>m>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于实现了 <see cref="ISoftDeletedEntity"/> 的实体）</param>
    /// <returns>结果包含实体条目</returns>
    IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate, bool includeDeleted = false);

    /// <summary>
    /// 异步获取实体条目
    /// </summary>
    /// <param name="id">实体条目标识符</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于实现了 <see cref="ISoftDeletedEntity"/> 的实体）</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含实体条目
    /// </returns>
    Task<TEntity> GetByIdAsync(long? id, bool includeDeleted = false, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取实体条目
    /// </summary>
    /// <param name="id">实体条目标识符</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于实现了 <see cref="ISoftDeletedEntity"/> 的实体）</param>
    /// <returns>
    /// 实体条目
    /// </returns>
    TEntity GetById(long? id, bool includeDeleted = false);

    /// <summary>
    /// 根据标识符获取多个实体条目
    /// </summary>
    /// <param name="ids">实体条目标识符集合</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于实现了 <see cref="ISoftDeletedEntity"/> 的实体）</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含实体条目集合
    /// </returns>
    Task<IList<TEntity>> GetByIdsAsync(IList<long> ids, bool includeDeleted = false, CancellationToken cancellationToken = default);

    /// <summary>
    /// 异步获取所有实体条目
    /// </summary>
    /// <param name="func">选择条目的函数</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于 <see cref="ISoftDeletedEntity"/> 实体）</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含实体条目集合
    /// </returns>
    Task<IList<TEntity>> GetAllAsync(Func<IQueryable<TEntity>, IQueryable<TEntity>> func = null,
        bool includeDeleted = false, CancellationToken cancellationToken = default);

    /// <summary>
    /// 获取所有实体条目
    /// </summary>
    /// <param name="func">选择条目的函数</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于 <see cref="ISoftDeletedEntity"/> 实体）</param>
    /// <returns>实体条目集合</returns>
    IList<TEntity> GetAll(Func<IQueryable<TEntity>, IQueryable<TEntity>> func = null,
        bool includeDeleted = false);


    /// <summary>
    /// 异步获取所有实体条目，分页返回
    /// </summary>
    /// <param name="func">选择条目的函数</param>
    /// <param name="pageIndex">页码</param>
    /// <param name="pageSize">每页条目数</param>
    /// <param name="getOnlyTotalCount">是否仅获取总条目数，不实际加载数据</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于 <see cref="ISoftDeletedEntity"/> 实体）</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含实体条目的分页列表
    /// </returns>
    Task<PagedList<TEntity>> GetAllPagedAsync(Func<IQueryable<TEntity>, IQueryable<TEntity>> func = null,
        int pageIndex = 0, int pageSize = int.MaxValue, bool getOnlyTotalCount = false, bool includeDeleted = false, CancellationToken cancellationToken = default);

    /// <summary>
    /// 异步获取所有实体条目，分页返回
    /// </summary>
    /// <param name="func">选择条目的函数</param>
    /// <param name="filter">分页过滤</param>
    /// <param name="getOnlyTotalCount">是否仅获取总条目数，不实际加载数据</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于 <see cref="ISoftDeletedEntity"/> 实体）</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含实体条目的分页列表
    /// </returns>
    Task<PagedList<TEntity>> GetAllPagedAsync(Func<IQueryable<TEntity>, IQueryable<TEntity>> func = null,
        PaginationFilter filter = null, bool getOnlyTotalCount = false, bool includeDeleted = false, CancellationToken cancellationToken = default);

    /// <summary>
    /// 异步获取所有实体条目，分页返回
    /// </summary>
    /// <param name="func">选择条目的函数</param>
    /// <param name="filter">分页过滤</param>
    /// <param name="includeDeleted">是否包含已删除的条目（仅适用于 <see cref="ISoftDeletedEntity"/> 实体）</param>
    /// <returns>
    /// </returns>
    IOrderedQueryable<TEntity> GetOrderedQueryable(
        Func<IQueryable<TEntity>, IQueryable<TEntity>> func = null,
        PaginationFilter filter = null,
        bool includeDeleted = false);

    /// <summary>
    /// 异步插入实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>表示异步操作的任务</returns>
    Task InsertAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 异步插入实体条目并返回插入后的实体（可能包含数据库生成的值）
    /// </summary>
    /// <param name="entity">实体条目</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>插入操作完成后的实体</returns>
    Task<TEntity> InsertAndGetAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 插入实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    void Insert(TEntity entity);

    /// <summary>
    /// 异步插入实体条目集合
    /// </summary>
    /// <param name="entities">实体条目集合</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>表示异步操作的任务</returns>
    Task InsertAsync(IList<TEntity> entities, CancellationToken cancellationToken = default);

    /// <summary>
    /// 插入实体条目
    /// </summary>
    /// <param name="entities">实体条目集合</param>
    void Insert(IList<TEntity> entities);

    /// <summary>
    /// 异步更新实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>表示异步操作的任务</returns>
    Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    void Update(TEntity entity);

    /// <summary>
    /// 根据条件更新
    /// </summary>
    /// <param name="setPropertyCalls">修改的列</param>
    /// <param name="predicate">条件</param>
    /// <returns></returns>
    void Update(
        Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls,
        Expression<Func<TEntity, bool>>
        predicate);

    /// <summary>
    /// 根据条件更新
    /// </summary>
    /// <param name="setPropertyCalls">修改的列</param>
    /// <param name="predicate">条件</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns></returns>
    Task UpdateAsync(
        Expression<Func<SetPropertyCalls<TEntity>,SetPropertyCalls<TEntity>>> setPropertyCalls,
        Expression<Func<TEntity, bool>>
        predicate, CancellationToken cancellationToken = default);

    /// <summary>
    /// 更新实体条目集合
    /// </summary>
    /// <param name="entities">实体条目集合</param>
    void Update(IList<TEntity> entities);

    /// <summary>
    /// 异步删除实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>表示异步操作的任务</returns>
    Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);

    /// <summary>
    /// 删除实体条目
    /// </summary>
    /// <param name="entity">实体条目</param>
    void Delete(TEntity entity);

    /// <summary>
    /// 异步删除实体条目集合
    /// </summary>
    /// <param name="entities">实体条目集合</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>表示异步操作的任务</returns>
    Task DeleteAsync(IList<TEntity> entities, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据传入的条件删除实体条目
    /// </summary>
    /// <param name="predicate">用于测试每个元素是否符合条件的函数</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>
    /// 表示异步操作的任务
    /// 任务结果包含已删除记录的数量
    /// </returns>
    Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);

    /// <summary>
    /// 根据传入的条件删除实体条目
    /// </summary>
    /// <param name="predicate">用于测试每个元素是否符合条件的函数</param>
    /// <returns>
    /// 已删除记录的数量
    /// </returns>
    int Delete(Expression<Func<TEntity, bool>> predicate);
    #endregion
}